/* 
 * Copyright 2013 Imanuel Rohlfing, Dennis Wittkötter

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/
package management.beans;

import java.io.Serializable;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.el.ELContext;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import management.constants.Names;
import management.ejb.DatabaseController;
import management.entities.*;


/**
 * Bean for Person objects.
 * This bean handles the database operations with the Person entities.
 * @author Imanuel Rohlfing
 */
@ManagedBean(name="persons")
@SessionScoped
public class PersonBean implements Serializable {
    
    /**
     * database controller
     */
    @EJB
    private DatabaseController dbC;
    
    /**
     * the current person
     */
    private Person current = new Person();
    
    /**
     * a list of all persons stored in the database
     */
    private List<Person> allPersons;
    
    /**
     * a picklist of rooms
     */
    private RoomPickListBean roomPickListB;
 
    /**
     * a LoginBean
     */
    private LoginBean loginBean;    
    
    
    /**
     * Default constructor
     */
    public PersonBean(){
        roomPickListB = (RoomPickListBean)getBean("roomPickList", RoomPickListBean.class);
        loginBean = (LoginBean)getBean("auth", LoginBean.class);
    }
    
    /**
     * Loads all persons from the databast into a local field.
     * Will be called after object construction.
     */
    @PostConstruct
    public void loadPersonList() {
        allPersons = dbC.getPersons();
    }

    /**
     * Persists the commited person to the database.
     * @param p Person object to persist to database
     * @return  link path for website redirection
     */
    public String add(Person p){
        if(!loginBean.isLoggedIn()){
            return "LOGIN";
        }
        try {         
            if( !dbC.identityCardNumberExists(p) ) {
                if( dbC.persist(p) ){
                    FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, Names.MSG_PERSON_CREATED_S, ""));
                    loadPersonList();
                }
                else{
                    FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, Names.MSG_PERSON_CREATED_F, ""));                 
                }
            }
            else{
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, Names.MSG_IDCARD_ALLREADY_EXISTS, ""));
            }
        } 
        catch(Exception e) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, Names.MSG_PERSON_CREATED_F, ""));
        }    
        p.setFirstName(null);
        p.setIdentityCardNumber(null);
        p.setLastName(null);
       
        return "SHOW_PERSON";
    }
    
    /**
     * Updates the current user in the database.
     * @return  link path for website redirection
     */
    public String edit(){
        if(!loginBean.isLoggedIn()){
            return "LOGIN";
        }        
        try{
            if( !dbC.identityCardNumberExists(current) ) {
                current.setRooms(roomPickListB.getData().getTarget());
                //roomPickListB.save();
                
                for(Room room : dbC.getRooms()) {
                    room.removePerson(current);
                    dbC.update(room);
                }

                for(Room room : current.getRooms()) {
                    room.setPerson(current);
                    dbC.update(room);
                }               

                if( dbC.update(current) ){
                    FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, Names.MSG_PERSON_EDITED_S, ""));
                    loadPersonList();
                    current = new Person();                    
                }
                else{
                    FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, Names.MSG_PERSON_EDITED_F, ""));
                    return "EDIT_PERSON";
                }
            }
            else{
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, Names.MSG_IDCARD_ALLREADY_EXISTS, ""));
                return "EDIT_PERSON";
            }
        }
        catch(Exception e){            
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, Names.MSG_PERSON_EDITED_F, ""));
            return "EDIT_PERSON";
        }
        return "SHOW_PERSON";
    }
    
    /**
     * Reads the id of a person from the current request parameter and searches 
     * for the relates person in database. If found the person will be updated.
     * @return  link path for website redirection
     */
    public String gotoEdit() {
        String id = getRequestParameter("edit");
        current = dbC.findPerson(id);
        if(current == null){
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, Names.MSG_PERSON_DOESNT_EXIST, ""));
            return "SHOW_PERSON";
        }
        roomPickListB.setCurrentPerson(current);
        
        return "EDIT_PERSON";
    }

    /**
     * Reads the id of a person from the current request parameter and searches 
     * for the relates person in database. If found the person will be deleted.
     * @return  link path for website redirection
     */
    public String gotoDelete() {
        if(!loginBean.isLoggedIn()){
            return "LOGIN";
        }
        
        
        for(Room room : dbC.getRooms()) {
            room.removePerson(current);
            dbC.update(room);
        }
        
        if( dbC.delete(current) ){
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, Names.MSG_PERSON_DELETED_S, ""));
            loadPersonList();
            current = new Person();
            return "SHOW_PERSON";
        }
        else{
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, Names.MSG_PERSON_DELETED_F, ""));
            return "EDIT_PERSON";
        }
    }    
    
    /**
     * Static method to get access to extern components.
     * @param <T>   type of the object of the component
     * @param beanName  name of the bean to get access on
     * @param clazz class of the bean to get access on
     * @return  the bean object to get access on
     */
    public static <T> T getBean(final String beanName, final Class<T> clazz) {
        ELContext elContext = FacesContext.getCurrentInstance().getELContext();
        return (T) FacesContext.getCurrentInstance().getApplication().getELResolver().getValue(elContext, null, beanName);
    }
    
    /**
     * Provides the value of the current request parameter.
     * @param par   faces parameter to read out
     * @return  value of the parameter
     */
    private String getRequestParameter(String par) { 
        return FacesContext.getCurrentInstance().getExternalContext()
                .getRequestParameterMap().get(par); 
    }

    /**
     * Provides the current person.
     * @return  current person object
     */
    public Person getCurrent(){
        return current;
    }
    
    /**
     * Provides a list of all persons stored in the database.
     * @return  list of all persons
     */
    public List<Person> getPersons(){
        return allPersons;
    }

    
}